"""

创建与新闻相关的视图函数

"""
from info import db
from info.models import News, Comment, CommentLike
from info.utils.common import user_data_session
from info.utils.response_code import RET
from . import news_blu
from flask import render_template, g, current_app, abort, request, jsonify


@news_blu.route("/<int:news_id>")
@user_data_session
def news_detail(news_id):
    """
    新闻详情页视图函数
    :param: 根据新闻ID返回相应的新闻内容
    :return:
    """

    # 需求一： 登陆新闻详情页，状态是跟随的
    # 思路，在请求一个新闻列表页面，要先读取session。让浏览器本地获取
    # 由于我们几乎每个页面都要获得用户的登陆会话状态，所以，我们要把这个每一次获取用户状态的代码进行封装
    # 获得用户的状态
    # user_id = session.get("user_id")
    # 我们把这个方法写成一个组件，并且用g变量来替代
    user = g.user

    # 需求二： 把对应ID的新闻内容给显示出来
    try:
        news_id = int(news_id)
    except Exception as e:
        current_app.logger.debug(e)

    # 根据ID查询新闻
    news = News.query.get(news_id)

    # print(news, type(news))

    # 需求三：根据用户登陆的状态把右侧的信息填满，如果用户未登陆状态，显示十条新闻，否则显示6条信息
    hot_news_list = None
    if not user:
        # 获取10条最新的新闻
        try:
            hot_news_list = News.query.order_by(News.clicks.desc()).limit(10)
        except Exception as e:
            current_app.logger.debug(e)
    else:
        try:
            hot_news_list = News.query.order_by(News.clicks.desc()).limit(6)
        except Exception as e:
            current_app.logger.debug(e)

    if not news:
        abort(404)
    else:
        # 每次正确访问后，就点击量加1
        news.clicks += 1
        db.session.commit()

    # 需求四：加载所有的评论列表
    # 思路，根据新闻ID把评论都查询出来
    result_comments = Comment.query.filter(Comment.news_id == news_id).all()
    # 查询当前用户，在所有的点赞的评论
    user_comment_like_list = []
    if user:
        try:
            temp_user_comment_like_list = CommentLike.query.filter_by(user_id=user.id).all()
        except Exception as e:
            current_app.logger.debug(e)
            return jsonify(errno=RET.DBERR, errmsg="查询数据库失败")
        for temp_user_comment_like in temp_user_comment_like_list:
            user_comment_like_list.append(temp_user_comment_like.to_dict())

    # 获取当前用户所有点赞的列表的评论ID
    user_comment_like_comment_id_list = []
    if len(user_comment_like_list) > 0:
        user_comment_like_comment_id_list = [user_comment_like["comment_id"] for user_comment_like in user_comment_like_list]

    comments = []  # 查询所有评论列表
    for item in result_comments:
        # 该用户是否点赞该评论的信息也添加进行
        commen = item.to_dict()  # 每一条评论
        commen["is_like"] = False  # 设置默认没点赞  给每一个评论设置一个点没点赞的键值对
        # 对每一个评论进行判断，看当前评论是否在用户点赞的列表中
        if commen["id"] in user_comment_like_comment_id_list:
            commen["is_like"] = True

        """
        {'user': 
            {'news_count': 1, 'gender': 'MAN', 'mobile': '17070855717', 'id': 1, 'followers_count': 0, 'nick_name': '毛大帅123', 'avatar_url': 'http://oyucyko3w.bkt.clouddn.com/http://oyucyko3w.bkt.clouddn.com/Fukdfjx2hKeZ1kLY2mhjm9lqZsOE', 'signature': '好好学习天天向上'}, 'content': '你获得事实上', 'parent': None, 'id': 1, 'news_id': 149, 'like_count': 0, 'create_time': '2018-07-20 19:29:53', 'is_like': False}

        """
        # 每个评论对应的头像
        commen["avatar_url"] = commen["user"]["avatar_url"]
        # 判断完后，把comment添加进conments中
        comments.append(commen)

    comments.reverse()

    # total_comment = len(comments)  不再从服务端获取总的评论的条数了

    # return render_template("news/detail.html", user=user, news=news, hot_news_list=hot_news_list,comments=comments,total_comment=total_comment)

    # 需求五 判断用户是否点赞过该评论。这样在页面显示的时候就会根据用户的状态，前端显示不同的样式
    # 从用户的收藏列表中查询
    is_collect = False
    if user and news in user.collection_news:
        is_collect = True
    # 查询当前用户所有的文章数和所有的粉丝数
    news_count = user.news_list.count()
    followers_count = user.followers.count()
    # print("+++++++++++++++++++++++++++++++")
    # print(news_count, followers_count)

    # 用户是否被当前用户关注
    is_focus = False
    if user in user.followers:
        is_focus = True

    return render_template("news/detail.html", user=user, news=news, hot_news_list=hot_news_list, comments=comments, is_collect=is_collect, news_count=news_count, followers_count=followers_count)


# 完成点击收藏的和取消的业务逻辑
@news_blu.route("/news_collect", methods=["POST"])
@user_data_session
def news_collect():
    """
    完成点击收藏和点击取消收藏的业务逻辑

    :param :    news_id	    int	    是	新闻id
    :param :    action	    string	是	指定两个值：'collect', 'cancel_collect'

    :return: json
        errno	int	是	错误码
        errmsg	string	是	错误信息
    """

    # 1 获取用户通过浏览器发来的参数
    collect_params = request.json

    news_id = collect_params.get("news_id")
    action = collect_params.get("action")

    # 2 对参数进行判断
    # 2.1 参数是否足够
    if not all([news_id, action]):
        return jsonify(errno=RET.PARAMERR, errmsg="参数不足")

    # 2.2 判断当前用户是否收藏过该信息
    user = g.user
    if not user:
        return jsonify(errno=RET.USERERR, errmsg="用户没有登陆，不能使用收藏功能")

    news = None
    try:
        news = News.query.get(news_id)
    except Exception as e:
        current_app.logger.debug(e)
        return jsonify(errno=RET.DBERR, errmsg="查询数据库失败")
    if not news:
        return jsonify(errno=RET.NODATA, errmsg="没有这条新闻")

    if action not in ("collect", "cancel_collect"):
        return jsonify(errno=RET.PARAMERR, errmsg="参数错误")
    # 查询当前用户是否关注过这条新闻
    if action == "collect":
        # 判断当前用户是否已经收藏了该新闻
        if news in user.collection_news:
            is_forced = True
            return jsonify(errno=RET.DATAEXIST, errmsg="用户已经关注过了，请不要再关注")
        else:
            # 填写关注信息
            user.collection_news.append(news)
            # 操作完后，提交
            db.session.commit()
            return jsonify(errno=RET.OK, errmsg="关注成功")  # 注意，不可以这个时候返回数据，因为此时数据数据还没有提交到数据库
    else:
        # 判断当前用户是否关注过
        if news in user.collection_news:
            user.collection_news.remove(news)
            # 操作完后，提交
            db.session.commit()
            return jsonify(errno=RET.OK, errmsg="取消关注成功")
        else:
            return jsonify(errno=RET.NODATA, errmsg="没有关注")


# 完成新闻评论内容
@news_blu.route("/news_comment", methods=["POST"])
@user_data_session
def news_comment():
    """
    完成新闻评论功能
    :param: news_id	        int	        是	新闻id
    :param: comment	        string	    是	评论内容
    :param: parent_id	    int	        否	回复的评论的id

    :return:
    """
    # 1 获取从前端页面传递来的数据
    user = g.user  # 先获取用户登陆状态  # 在调试的时候，这里出了问题。说_AppCtxGlobals' object has no attribute 'user'  原因是没有把获取g变量的

    comment_params = request.json
    news_id = comment_params.get("news_id")
    comment_content = comment_params.get("comment")
    parent_id = comment_params.get("parent_id")

    # 2 对所获取的数据进行判断
    try:
        news_id = int(news_id)
        if parent_id:
            parent_id = int(parent_id)
    except Exception as e:
        current_app.logger.debug(e)
        return jsonify(errno=RET.PARAMERR, errmsg="参数错误")

    if not user:
        return jsonify(errno=RET.USERERR, errmsg="用户未登陆")

    if not all([news_id, comment_content]):
        return jsonify(errno=RET.PARAMERR, errmsg="参数不足")

    # 如果上述OK，我们把评论内容填写进去
    try:
        # 根据新闻ID查询到该条新闻
        news = News.query.get(news_id)
    except Exception as e:
        current_app.logger.debug(e)
        return jsonify(errno=RET.DBERR, errmsg="数据库查询失败")
    if not news:
        # 直接抛出一个404异常
        # abort(404)  # 或者使用下面的
        return jsonify(errno=RET.DBERR, errmsg="找不到该条新闻")

    # 3 对数据根据需求进行处理
    # 根据新闻ID，和新闻内容，以及跟随ID把数据填写进数据库
    # 对评论表进行操作
    comment = Comment()  # 新建一个评论对象
    comment.content = comment_content
    comment.news_id = news_id
    comment.user_id = user.id
    if parent_id:
        comment.parent_id = parent_id

    try:
        db.session.add(comment)
        db.session.commit()
    except Exception as e:
        current_app.logger.debug(e)
        return jsonify(errno=RET.DBERR, errmsg="保存评论内容失败")
    # 4 把结果返回给前端 前端还需要评论的内容，顺便把评论内容也给前端
    return jsonify(errno=RET.OK, errmsg="评论成功", comment=comment.to_dict())


# 实现点赞和取消赞的功能
@news_blu.route('/comment_like', methods=["POST"])
@user_data_session
def comment_like():
    """
    实现点赞和取消点赞的功能
    comment_id	    int	    是	评论id
    news_id	        int	    是	新闻id
    action	        string	是	点赞操作类型：add(点赞)，remove(取消点赞)

    :return: jsons
    """
    # 1 获取参数
    # 1.1 获取用户登陆状态
    user = g.user
    comment_like_params = request.json

    comment_id = comment_like_params.get("comment_id")
    news_id = comment_like_params.get("news_id")
    action = comment_like_params.get("action")

    # 2 验证参数
    if not user:
        return jsonify(errno=RET.USERERR, errmsg="用户未登陆")

    if not all(["comment_id", "news_id", "action"]):
        return jsonify(errno=RET.PARAMERR, errmsg="参数不足")

    try:
        comment_id = int(comment_id)
        news_id = int(news_id)
    except Exception as e:
        current_app.logger.debug(e)
        return jsonify(errno=RET.PARAMERR, errmsg="参数错误")

    if action not in ["add", "remove"]:
        return jsonify(errno=RET.PARAMERR, errmsg="参数错误")

    # 查询评论是否存在
    try:
        comment = Comment.query.get(comment_id)
    except Exception as e:
        return jsonify(errno=RET.DBERR, errmsg="数据库查询失败")
    if not comment:
        return jsonify(errno=RET.NODATA, errmsg="没有这条评论")

    # 3 根据参数进行业务逻辑
    # 先判断用户是否以及点赞该新闻
    resulet_comment_like = CommentLike.query.filter_by(comment_id=comment_id, user_id=user.id).first()
    # resulet_comment_like = CommentLike.query.filter_by(CommentLike.comment_id==comment_id, CommentLike.user_id==user.id).first()  这种写法跟上面的是一样的
    # 再判断动作行为
    if action == "add":

        if not resulet_comment_like:
            # 添加关注
            comment_like = CommentLike()
            comment_like.comment_id = comment_id
            comment_like.user_id = user.id
            try:
                db.session.add(comment_like)
                # 评论的点赞数+1
                comment.like_count += 1

                db.session.commit()
            except Exception as e:
                return jsonify(errno=RET.DBERR, errmsg="点赞信息写入数据库失败")
            # 4 反馈结果
            return jsonify(errno=RET.OK, errmsg="点赞成功")

        else:
            return jsonify(errno=RET.DATAEXIST, errmsg="用户已经点赞")
    else:

        if resulet_comment_like:
            # 如果存在关注就删除关注
            comment_like = CommentLike.query.filter_by(comment_id=comment_id, user_id=user.id).first()

            db.session.delete(comment_like)

            # 评论的点赞数减一
            comment.like_count -= 1

            try:
                db.session.commit()
            except Exception as e:
                return jsonify(errno=RET.DBERR, errmsg="连接数据库失败")

            return jsonify(errno=RET.OK, errmsg="取消点赞成功")

        else:
            return jsonify(errno=RET.DATAERR, errmsg="用户未点赞")
